#include <SDL/SDL.h>

#include "window.h"

namespace SkyID
{

//- Window --------------------------------------------------------------------

namespace Window
{

static bool gRun;
static uint32 gWidth, gHeight;

static KeyboardCallback     gKeyboardCallback    = NULL;
static MouseMotionCallback  gMouseMotionCallback = NULL;
static MouseButtonCallback  gMouseButtonCallback = NULL;

bool initialize(const Config &config)
{
	if (SDL_Init(SDL_INIT_VIDEO) < 0)
	{
		LOG_MSG("Window: init failed");
		return false;
	}

	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

	gWidth = config.windowWidth;
	gHeight = config.windowHeight;

	if (SDL_SetVideoMode(gWidth, gHeight, 32, SDL_OPENGL) == 0)
	{
		LOG_MSG("Window: creation failed");
		return false;
	}

	SDL_WM_SetCaption("Sky-ID", "Sky-ID");

	if (config.hideCursor)
		SDL_ShowCursor(SDL_DISABLE);

	gRun = true;

	LOG_MSG("Window: initialized");
	return true;
}

void shutdown()
{
	SDL_Quit();
	LOG_MSG("Window: shutdown");
}

uint32 getWidth()
{
	return gWidth;
}

uint32 getHeight()
{
	return gHeight;
}

bool processEvents()
{
	if (!gRun)
		return false;

	SDL_Event event;
	while (SDL_PollEvent(&event)) 
	{
		switch (event.type) 
		{
		case SDL_KEYDOWN:
		case SDL_KEYUP:
			if (gKeyboardCallback)
			{
				KeyboardEvent ke;
				//ke.userData = gUserData;
				ke.pressed = (event.key.state == SDL_PRESSED);
				//ke.unicode = event.key.keysym.unicode;
				ke.key = static_cast<KeyCode>(event.key.keysym.sym);
				ke.mod = static_cast<KeyMod>(event.key.keysym.mod);
				CALLBACK(gKeyboardCallback, ke);
			}
			break;
		case SDL_MOUSEMOTION:
			if (gMouseMotionCallback)
			{
				MouseMotionEvent mm;
				//mm.userData = gUserData;
				//mm.buttonState = event.motion.state;
				mm.x = event.motion.x;
				mm.y = event.motion.y;
				mm.dx = event.motion.xrel;
				mm.dy = event.motion.yrel;
				CALLBACK(gMouseMotionCallback, mm);
			}
			break;
		case SDL_MOUSEBUTTONUP:
		case SDL_MOUSEBUTTONDOWN:
			if (gMouseButtonCallback)
			{
				MouseButtonEvent mb;
				//mb.userData = gUserData;
				mb.pressed = (event.button.state == SDL_PRESSED);
				mb.x = event.button.x;
				mb.y = event.button.y;
				mb.button = static_cast<MouseButton>(event.button.button);
				CALLBACK(gMouseButtonCallback, mb);
			}
			break;
		case SDL_QUIT:
			gRun = false;
			break;
		}
	}

	return gRun;
}

void swapBuffers()
{
	SDL_GL_SwapBuffers();
}

uint32 getTicks()
{
	return (uint32)SDL_GetTicks();
}

bool getKeyState(KeyCode key)
{
	int keyCount = 0;
	uchar *keys = SDL_GetKeyState(&keyCount);
	return key < keyCount ? (bool)keys[key] : false;
}

void quit()
{
	gRun = false;
}

void setKeyboardCallback(KeyboardCallback callback)
{
	gKeyboardCallback = callback;
}

void setMouseMotionCallback(MouseMotionCallback callback)
{
	gMouseMotionCallback = callback;
}

void setMouseButtonCallback(MouseButtonCallback callback)
{
	gMouseButtonCallback = callback;
}

} // namespace Window

} // namespace SkyID
